#include <linux/init.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/of.h>
#include <linux/stat.h>
#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <asm/uaccess.h>
#include <linux/types.h>
#include <linux/kernel.h>

#define GPIO_LOW 0
#define GPIO_HIGH 1

//  定义设备文件名
#define DEVICE_NAME "gpiogate"
static int gpio_state = 0;
static unsigned char mem[10000];
//gpio——id
static int gpio;

static void mos_short(int gpio){
        int i;
        for(i = 0;i<10;i++){
            gpio_set_value(gpio,GPIO_LOW);
            mdelay(500);
            gpio_set_value(gpio,GPIO_HIGH);
            mdelay(500);
        printk("mos short\n");
        }
    
}
static int firefly_gate_probe(struct platform_device *pdev)
{
    int ret = -1;
    int i;
    enum of_gpio_flags flag;
    struct device_node *gate_node = pdev->dev.of_node;
    gpio = of_get_named_gpio_flags(gate_node, "gpio", 0, &flag);
    printk(KERN_INFO "gate_gpio is %d\n", gpio);
    if (!gpio_is_valid(gpio))
    {
        printk(KERN_INFO "gate_gpio fail");
        return -1;
    }
    ret = gpio_request(gpio, "gate_gpio");
    if (ret != 0)
    {
        gpio_free(gpio);
        return -EIO;
    }
    //必须先设置一次电频，不然不能控制该gpio
    gpio_direction_output(gpio,GPIO_LOW);
    mos_short(gpio);
    return 0;
}

static int firefly_gate_remove(struct platform_device *pdev)
{
    return 0;
}

static const struct of_device_id of_firefly_gate_match[] = {
        {.compatible = "firefly,gate"}
    };

static struct platform_driver firefly_gate_dirver = {
    .probe = firefly_gate_probe,
    .remove = firefly_gate_remove,
    .driver = {
        .name = "firefly_gate",
        .owner = THIS_MODULE,
        .of_match_table = of_firefly_gate_match}};

static ssize_t gpio_state_read(struct file *file, char __user *buf,
                               size_t count, loff_t *ppos)
{
    unsigned char temp[4];

    temp[0] = gpio_state >> 24;
    temp[1] = gpio_state >> 16;
    temp[2] = gpio_state >> 8;
    temp[3] = gpio_state;
    if (copy_to_user(buf, (void *)temp, 4))
    {
        return -EINVAL;
    }
    return count;
}

static ssize_t gpio_state_write(struct file *file, const char __user *buf,
                                size_t count, loff_t *ppos)
{
    ssize_t written = count;
    if ((*buf) == '0')
    {
        gpio_state = GPIO_LOW;
    }
    else
    {
        gpio_state = GPIO_HIGH;
    }
    gpio_set_value(gpio, gpio_state);
    return written;
}
//  描述与设备文件触发的事件对应的回调函数指针
static struct file_operations dev_fops =
    {.owner = THIS_MODULE, .read = gpio_state_read, .write = gpio_state_write};

//  描述设备文件的信息
static struct miscdevice misc =
    {
        .minor = MISC_DYNAMIC_MINOR,
        .name = DEVICE_NAME,
        .fops = &dev_fops
        // .mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH
        };

static int __init gate_init(void)
{
    int ret;
    //  建立设备文件
    ret = platform_driver_register(&firefly_gate_dirver);
    //  建立控制设备文件
    ret = misc_register(&misc);
    return platform_driver_register(&firefly_gate_dirver);
}
static void gate_exit(void)
{
    platform_driver_unregister(&firefly_gate_dirver);
    //  删除设备文件
    misc_deregister(&misc);
}
subsys_initcall(gate_init);
module_exit(gate_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("TongMing Xian 2018");
MODULE_DESCRIPTION("Gate controller Kernel Module for Firefly-Rk3288");